package com.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.base.entity.bo.SciencePersonBo;
import com.base.entity.vo.SciencePersonVo;
import com.base.mapper.SciencePersonMapper;
import com.base.service.SciencePersonService;
import com.cfg.service.CfgCategoryService;
import com.common.api.ApprovalApi;
import com.common.core.domain.AjaxResult;
import com.common.core.domain.entity.SysUser;
import com.common.core.domain.model.LoginUser;
import com.common.utils.CurrentRoleUtils;
import com.common.utils.QueryWrapperUtils;
import com.common.utils.SecurityUtils;
import com.common.utils.StringUtils;
import com.common.utils.bean.BizProcessMessages;
import com.common.utils.bean.ReflectionUtils;
import com.common.utils.uuid.IdUtils;
import com.flowable.domain.vo.task.BpmTaskApproveReqVO;
import com.flowable.service.IFlowTaskService;
import com.project.comom.NumberDealUtils;
import com.project.domain.bo.AllAlterationInfoBo;
import com.project.domain.bo.AlterationBo;
import com.project.domain.entity.*;
import com.project.domain.entity.xjProject.BizXjProject;
import com.project.domain.entity.zxProject.BizZxProject;
import com.project.domain.vo.*;
import com.project.mapper.AlterationBudgetMapper;
import com.project.mapper.AlterationMapper;
import com.project.mapper.AlterationMemberMapper;
import com.project.service.IBizProjectAlterationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service("biz_project_alteration")
public class AlterationServiceImpl implements IBizProjectAlterationService {

    @Autowired
    private AlterationMapper alterationMapper;

    @Autowired
    AlterationMemberMapper memberMapper;

    @Autowired
    AlterationBudgetMapper budgetMapper;

    @Autowired
    CfgCategoryService cfgCategoryService;

    @Autowired
    BudgetStandardServiceImpl budgetStandardService;

    @Autowired
    ProjectInitServiceImpl projectInitService;

    @Autowired
    ProjectMemberServiceImpl projectMemberService;

    @Autowired
    ProjectBudgetServiceImpl projectBudgetService;

    @Autowired
    YfContractServiceImpl yfContractService;

    //发起流程
    @Autowired
    private ApprovalApi approvalApi;

    //流程引擎
    @Autowired
    private IFlowTaskService flowTaskService;

    @Autowired
    ProjectMiddleCheckServiceImpl middleCheckService;

    @Autowired
    private ProCheckCommon checkCommon;

    @Autowired
    SciencePersonService sciencePersonService;

    @Autowired
    SciencePersonMapper sciencePersonMapper;

    //region 变更主表

    /**
     * 左上角根据状态的数量统计
     * @param alterationBo
     * @return
     */
    public List<NavigationForProVo.NameAndCount> selectGroups(AlterationBo alterationBo){
        List<NavigationForProVo.NameAndCount> res = new ArrayList<>();
        try{
            QueryWrapper<NavigationForProVo.NameAndCount> queryWrapper = new QueryWrapper<>();
            queryWrapper = this.getConditions(queryWrapper,alterationBo,"group"); //拼条件

            QueryWrapperUtils.getParamsProBusiness(queryWrapper,SecurityUtils.getLoginUser().getUser()); //用户权限
            QueryWrapperUtils.handleChangeType(queryWrapper,alterationBo.getChangeType());//处理变更类型字段

            res = alterationMapper.selectGroups(queryWrapper,alterationBo);
        }catch (Exception exception){
            String ex = exception.getMessage();
            res = null;
        }

        return res;
    }

    /**
     * 查询项目变更列表
     * @param alterationBo 项目变更
     * @param type 操作类型
     * @return 项目变更
     */
    @Override
    public IPage<BizProjectAlteration> selectBizProjectAlterationList(AlterationBo alterationBo, String type)
    {
        IPage<BizProjectAlteration> res = new Page<>();
        try{
            QueryWrapper<BizProjectAlteration> queryWrapper = new QueryWrapper<>();
            queryWrapper = this.getConditions(queryWrapper,alterationBo,"list"); //拼条件

            QueryWrapperUtils.getParamsProBusiness(queryWrapper,SecurityUtils.getLoginUser().getUser()); //用户权限
            QueryWrapperUtils.handleChangeType(queryWrapper,alterationBo.getChangeType());//处理变更类型字段
            //处理排序字段
            String orderStr = StringUtils.isNotBlank(alterationBo.getOrderStr())?alterationBo.getOrderStr():"createdate";
            String orderType = StringUtils.isNotBlank(alterationBo.getOrderType())?alterationBo.getOrderType():"desc";
            alterationBo.setOrderStr(projectInitService.changeStringToUp(orderStr));
            alterationBo.setOrderType(orderType);

            if(type.equals("select")){
                IPage<BizProjectAlteration> myPage = new Page<>(alterationBo.getPageNo(), alterationBo.getPageSize());
                res = alterationMapper.selectListInfos(myPage,queryWrapper,alterationBo);
                res = middleCheckService.getCheckInfosForList(res,"项目变更",BizProjectAlteration::setTaskId,BizProjectAlteration::setIsAuditor,BizProjectAlteration::getProcessInstanceId);
            }else{
                IPage<BizProjectAlteration> myPage = new Page<>(1, 1000);
                res = alterationMapper.selectListInfosForExport(myPage,queryWrapper,alterationBo);
            }
        }catch (Exception exception){
            String ex = exception.getMessage();
            res = null;
        }

        return res;
    }

    /**
     * 拼接条件
     * @param queryWrapper
     * @param alterationBo
     * @return
     */
    private QueryWrapper getConditions(QueryWrapper queryWrapper,AlterationBo alterationBo,String funType){
        try{
            alterationBo.setUnitId(addQuotationToStr(alterationBo.getUnitId()));//处理所属单位id
            //处理结项日期字段（年份4、年月7、年月日）
            String startChangeTime = changeDateString(alterationBo.getStartChangeTime(),"start");
            String endChangeTime = changeDateString(alterationBo.getEndChangeTime(),"end");

            queryWrapper.ge(StringUtils.isNotBlank(startChangeTime), "ALTER_DATE", startChangeTime)
                    .le(StringUtils.isNotBlank(endChangeTime), "ALTER_DATE", endChangeTime);
            if(funType.equals("list")){
                queryWrapper.eq(StringUtils.isNotBlank(alterationBo.getProClass()), "zb.CLASS_ID", alterationBo.getProClass())
                        .eq(StringUtils.isNotBlank(alterationBo.getCheckstatusByGroup()), "zb.CHECKSTATUS", alterationBo.getCheckstatusByGroup());
            }else{
                queryWrapper.eq(StringUtils.isNotBlank(alterationBo.getProClass()), "CLASS_ID", alterationBo.getProClass());
            }

            return queryWrapper;
        }catch (Exception exception){
            return queryWrapper;
        }
    }

    /**
     * 查询项目变更详情
     *
     * @param ID 项目变更主键
     * @return 项目变更
     */
    @Override
    public AllAlterationInfoVo selectBizProjectAlterationByID(String ID)
    {
        AllAlterationInfoVo allAlterationInfoVo = new AllAlterationInfoVo();

        //变更基础信息
        BizProjectAlteration baseInfo = alterationMapper.selectById(ID);
        String alterationType = baseInfo.getAlterType();
        String proId = baseInfo.getProjectId();

        String feeAuthorize = baseInfo.getChangeFeeAuthorize();
        if(alterationType.contains("feeAuthorize") && StringUtils.isNotBlank(feeAuthorize)){
            //处理合同变更金额
            baseInfo.setChangeFeeAuthorize(Double.toString(Double.valueOf(feeAuthorize)/10000));
        }
        allAlterationInfoVo.setBizProjectAlteration(baseInfo);


        if(alterationType.contains("member")){
            //变更成员信息
            BizProjectMemberAlteration bizProjectMemberAlteration = new BizProjectMemberAlteration();
            bizProjectMemberAlteration.setProjectAlterationId(ID);
            allAlterationInfoVo.setMemberAlterationsList(this.getMemberList(bizProjectMemberAlteration));
        }

        if(alterationType.contains("liuxiaoBudget")){
            //变更预算信息
            BizProjectBudgetAlteration bizProjectBudgetAlteration = new BizProjectBudgetAlteration();
            bizProjectBudgetAlteration.setProjectAlterationId(ID);
            allAlterationInfoVo.setBudgetAlterationList(this.getBudgetList(bizProjectBudgetAlteration,proId));
        }

        return allAlterationInfoVo;
    }

    /**
     * 保存项目变更(审核逻辑处理)
     * @param bizProjectAlterationBo 项目变更
     * @return 结果
     */
    @Override
    public AjaxResult saveBizProjectAlteration(AllAlterationInfoBo bizProjectAlterationBo)
    {
        String alterationId = "";
        String processInstanceId = "";
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String currentRoleKey = CurrentRoleUtils.getCurrentRoleKey(); //当前角色
        BizProjectAlteration baseInfo = bizProjectAlterationBo.getBaseInfos();
        if(baseInfo != null){
            Integer submitType = baseInfo.getSubmitType();
            String checkStatus = baseInfo.getCheckstatus();
            String operateType = StringUtils.isNotBlank(baseInfo.getID())?"edit":"add";
            if(submitType != null){
                switch (submitType){
                    case -1:{
                        //暂存：新建编辑都只保存信息，不做任何其他操作
                        if(!currentRoleKey.equals("biz_kyms") && !currentRoleKey.equals("biz_kycgly") || !StringUtils.isNotBlank(checkStatus)){
                            baseInfo.setCheckstatus("-1");//科研管理员、秘书的暂存都不改状态
                        }
                        bizProjectAlterationBo.setBaseInfos(baseInfo);
                        alterationId = this.saveAlterationInfos(bizProjectAlterationBo,operateType);
                        return StringUtils.isNotBlank(alterationId)?alterationId.contains("失败")?AjaxResult.error(alterationId):AjaxResult.success(BizProcessMessages.SAVE_SUCCESS):AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                    }
                    case 1:{
                        //提交（科研人员）：新建编辑均保存信息+发起流程
                        baseInfo.setCheckstatus("1");
                        baseInfo = ReflectionUtils.updateFields(baseInfo, BizProjectAlteration.class);
                        bizProjectAlterationBo.setBaseInfos(baseInfo);
                        alterationId = this.saveAlterationInfos(bizProjectAlterationBo,operateType);
                        if(StringUtils.isNotBlank(alterationId)){
                            if(alterationId.contains("失败")){
                                return AjaxResult.error(alterationId);
                            }else{
                                processInstanceId = approvalApi.businessEntryApproval(alterationId, "项目变更");
                                if(!StringUtils.isNotBlank(processInstanceId)){
                                    //发起流程并返回示例id
                                    //保存成功但流程实例id为空 -> 发起流程失败
                                    baseInfo.setCheckstatus("-1");
                                    bizProjectAlterationBo.setBaseInfos(baseInfo);
                                    this.saveAlterationInfos(bizProjectAlterationBo,operateType);
                                    return AjaxResult.warn(BizProcessMessages.SAVE_PARTIAL_SUCCESS);
                                }else{
                                    return AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
                                }
                            }
                        }else{
                            return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                        }
                    }
                    case 2:{
                        //保存并通过（管理员）：审核中且是当前审核人-》调流程接口；直接通过-》实例id为0
                        if(operateType.equals("add") || operateType.equals("edit") && (!StringUtils.isNotBlank(checkStatus) || StringUtils.isNotBlank(checkStatus)&&!checkStatus.equals("1"))){
                            //审核状态是暂存*不通过 -》直接将实例id置为0
                            baseInfo = ReflectionUtils.updateFields(baseInfo, BizProjectAlteration.class);
                            baseInfo.setProcessInstanceId("0");
                            baseInfo.setCheckstatus("2");
                            bizProjectAlterationBo.setBaseInfos(baseInfo);
                            alterationId = this.saveAlterationInfos(bizProjectAlterationBo,operateType);
                            if(StringUtils.isNotBlank(alterationId)){
                                if(alterationId.contains("失败")){
                                    return AjaxResult.error(alterationId);
                                }else{
                                    this.updateBusinessStatus("biz_project_alteration",alterationId,"2",loginUser.getUser().getUserRealId());
                                    return AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
                                }
                            }else{
                                return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                            }
                        }else{
                            //审核状态为审核中且是当前审核人（审核人逻辑前端处理）：保存并调流程接口
                            try{
                                alterationId = this.saveAlterationInfos(bizProjectAlterationBo,operateType);
                                if(StringUtils.isNotBlank(alterationId)){
                                    BpmTaskApproveReqVO bta = new BpmTaskApproveReqVO();
                                    bta.setId(baseInfo.getTaskId());
                                    bta.setReason(SecurityUtils.getNickName() + "保存并通过");
                                    flowTaskService.approveTask(SecurityUtils.getUserId(), bta);
                                    return AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
                                }else{
                                    return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                                }
                            }catch (Exception exception){
                                return AjaxResult.warn(BizProcessMessages.SAVE_SUCCESS_APPROVE_FAIL);
                            }

                        }
                    }
                    default: return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                }
            }else{
                baseInfo.setCheckstatus("-1");
                bizProjectAlterationBo.setBaseInfos(baseInfo);
                alterationId = this.saveAlterationInfos(bizProjectAlterationBo,operateType);
                return StringUtils.isNotBlank(alterationId)?AjaxResult.success(BizProcessMessages.SAVE_SUCCESS):AjaxResult.error(BizProcessMessages.SAVE_FAIL);
            }
        }else{
            return AjaxResult.warn("未获取到变更信息！");
        }
    }

    /**
     * 保存变更（业务处理）
     * @param bizProjectAlterationBo
     * @param operateType
     * @return
     */
    public String saveAlterationInfos(AllAlterationInfoBo bizProjectAlterationBo,String operateType){
        String res = "";
        BizProjectAlteration baseInfo = bizProjectAlterationBo.getBaseInfos();

        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        Date date = new Date();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        String alterId = baseInfo.getID();

        String alterDate = baseInfo.getAlterDate();
        if(StringUtils.isNotBlank(alterDate)){
            baseInfo.setAlterDate(alterDate + " 00:00:00");
        }

        try{
            //处理延期时间
            if(!StringUtils.isNotBlank(baseInfo.getChangePlanEndDate())){
                baseInfo.setChangePlanEndDate(null);
            }else{
                //判断延期时间格式
                if(middleCheckService.isValidTimeFormat(baseInfo.getChangePlanEndDate(),"yyyy-MM-dd") && middleCheckService.isValidTimeFormat(baseInfo.getChangePlanEndDate(),"yyyy-MM-dd  HH:mm:ss")){
                    return "保存失败，时间格式错误！";
                }
            }

            //判断项目委托时间格式
            if(baseInfo.getAlterType().contains("mandatary")){
                boolean wtStartTime = middleCheckService.isValidTimeFormat(baseInfo.getMandatarybegindate(),"yyyy-MM-dd") && middleCheckService.isValidTimeFormat(baseInfo.getMandatarybegindate(),"yyyy-MM-dd  HH:mm:ss");
                boolean wtEndTime = middleCheckService.isValidTimeFormat(baseInfo.getMandataryenddate(),"yyyy-MM-dd") && middleCheckService.isValidTimeFormat(baseInfo.getMandataryenddate(),"yyyy-MM-dd  HH:mm:ss");
                if(wtStartTime || wtEndTime){
                    return "保存失败，时间格式错误！";
                }
            }

            //处理合同金额
            String feeAuthorize = baseInfo.getChangeFeeAuthorize();
            if(baseInfo.getAlterType().contains("feeAuthorize") && StringUtils.isNotBlank(feeAuthorize)){
                baseInfo.setChangeFeeAuthorize(Double.toString(Double.parseDouble(feeAuthorize)*10000));
            }

            int saveRes = 0;
            baseInfo.setLasteditdate(dateFormat.parse(dateFormat.format(date)));
            baseInfo.setLasteditusername(loginUser.getNickName());
            baseInfo.setLastedituserid(loginUser.getUserRealId());

            //项目变更只传proId，项目其他基础信息需要根据proId去获取
            VProject proInfo = projectInitService.baseDetail(baseInfo.getProjectId());
            if(proInfo != null){
                baseInfo.setProjectName(proInfo.getName());
                baseInfo.setChargerName(proInfo.getChargerName());
                baseInfo.setUnitId(proInfo.getUnitId());
                baseInfo.setAlterDate(dateFormat.format(date));
                baseInfo.setChargerCode(proInfo.getChargerCode());

                if(operateType.equals("add")){
                    baseInfo.setCreatedate(dateFormat.parse(dateFormat.format(date)));
                    baseInfo.setCreateuserid(loginUser.getUserRealId());
                    baseInfo.setCreateusername(loginUser.getNickName());

                    alterId = IdUtils.simpleUUID();
                    baseInfo.setID(alterId);
                    saveRes = alterationMapper.insert(baseInfo);
                }else{
                    saveRes = alterationMapper.updateById(baseInfo);
                }

                //处理成员从表和预算从表
                this.saveMemberInfos(bizProjectAlterationBo.getMemberAlterations(),alterId,operateType);
                this.saveBudgetInfos(bizProjectAlterationBo.getBudgetAlterationList(),alterId);

                if(saveRes > 0){
                    res = alterId;
                }
            }
        }catch (Exception exception){
            String ex = exception.getMessage();
        }

        return res;
    }

    /**
     * 批量删除项目变更列
     *
     * @param IDs 需要删除的项目变更列主键
     * @return 结果
     */
    @Override
    public String deleteBizProjectAlterationByIDs(String[] IDs)
    {
        String res = "操作成功！";
        try{
            List<String> idList = Arrays.stream(IDs).collect(Collectors.toList());
            idList.forEach(id->deleteBizProjectAlterationByID(id));
        }catch (Exception exception){
            res = "操作失败！" + exception.getMessage();
        }
        return res;
    }

    /**
     * 删除项目变更列信息
     *
     * @param ID 项目变更列主键
     * @return 结果
     */
    @Override
    public String deleteBizProjectAlterationByID(String ID)
    {
        String res = "操作成功！";
        try{
            BizProjectAlteration baseInfo = alterationMapper.selectById(ID);
            if(baseInfo != null){
                String alterType = baseInfo.getAlterType();
                if(alterType.equals("member")){
                    //删除成员从表信息
                    BizProjectMemberAlteration bizProjectMemberAlteration = new BizProjectMemberAlteration();
                    bizProjectMemberAlteration.setProjectAlterationId(ID);
                    res = deleteMemberInfos(bizProjectMemberAlteration);
                }

                if(alterType.equals("liuxiaoBudget")){
                    //删除预算从表信息
                    BizProjectBudgetAlteration bizProjectBudgetAlteration = new BizProjectBudgetAlteration();
                    bizProjectBudgetAlteration.setProjectAlterationId(ID);
                    res = deleteBudgetInfos(bizProjectBudgetAlteration);
                }

                //删除主信息
                alterationMapper.deleteById(ID);
            }
        }catch (Exception exception){
            res = "操作失败！" + exception.getMessage();
        }
        return res;
    }


    /**
     * 给字符串加引号
     * @param oldStr
     * @return
     */
    public String addQuotationToStr(String oldStr){
        if(StringUtils.isNotBlank(oldStr)){
            String newStr = oldStr.replace(",","','");
            return newStr ;
        }else{
            return oldStr;
        }
    }

    /**
     * 处理其他时间字符串
     * @param dateStr
     * @param startOrEnd
     * @return
     */
    public String changeDateString(String dateStr,String startOrEnd){
        if(StringUtils.isNotBlank(dateStr)){
            int strLength = dateStr.length();
            if(startOrEnd.equals("start")){
                if(strLength == 4){
                    dateStr = dateStr + "-01-01 00:00:00";
                }else if(strLength == 7){
                    dateStr = dateStr + "-01 00:00:00";
                }if(strLength == 10){
                    dateStr = dateStr + " 00:00:00";
                }
            }else{
                if(strLength == 4){
                    dateStr = dateStr + "-12-31 23:59:59";
                }else if(strLength == 7){
                    dateStr += "-01"; // 默认到每月的第一天
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                    LocalDate date = LocalDate.parse(dateStr, formatter);
                    LocalDate lastDayOfMonth = date.withDayOfMonth(date.lengthOfMonth());
                    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                    dateStr = lastDayOfMonth.format(outputFormatter) + " 23:59:59";
                }else if(strLength == 10){
                    dateStr = dateStr + " 23:59:59";
                }
            }
        }
        return dateStr;
    }
    //endregion

    //region 变更成员从表

    /**
     * 查询变更成员从表
     * @param bizProjectMemberAlteration
     * @return
     */
    public List<BizProjectMemberAlteration> getMemberList(BizProjectMemberAlteration bizProjectMemberAlteration){
        QueryWrapper<BizProjectMemberAlteration> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("PROJECT_ALTERATION_ID",bizProjectMemberAlteration.getProjectAlterationId())
//                .ne("JOIN_STATE_ID","0")
                .orderByAsc("ORDER_ID");
        return memberMapper.selectList(queryWrapper);
    }

    /**
     * 保存成员变更从表信息
     * @param memberAlterationsList
     * @param alterId
     * @param operateType
     * @return
     */
    public String saveMemberInfos(List<BizProjectMemberAlteration> memberAlterationsList,String alterId,String operateType){
        String res = "操作成功！";
        try{
            //先全部删除
            BizProjectMemberAlteration bizProjectMemberAlteration = new BizProjectMemberAlteration();
            bizProjectMemberAlteration.setProjectAlterationId(alterId);
            deleteMemberInfos(bizProjectMemberAlteration);
            //再全部插入
            for(int m =0;m<memberAlterationsList.size();m++){
                BizProjectMemberAlteration memberAlteration = memberAlterationsList.get(m);
                if(operateType.equals("add")){
                    //如果是新增，人员数据是从Member表获取的，要把id给ProjectMemberId
                    memberAlteration.setProjectMemberId(memberAlteration.getID());
                }

                memberAlteration.setID(null);
                memberAlteration.setProjectAlterationId(alterId);
                memberAlteration.setOrderId((long)m+1);

                //如果人员参与状态为空，就默认是参与
                String joinState = memberAlteration.getJoinStateId();
                if(!StringUtils.isNotBlank(joinState)){
                    memberAlteration.setJoinStateId("1");
                }
                memberMapper.insert(memberAlteration);
            }
        }catch (Exception exception){
            res = "操作失败！" + exception.getMessage();
        }
        return res;
    }

    /**
     * 删除变更成员信息
     * @param bizProjectMemberAlteration
     * @return
     */
    public String deleteMemberInfos(BizProjectMemberAlteration bizProjectMemberAlteration){
        String res = "操作成功！";
        try {
            QueryWrapper<BizProjectMemberAlteration> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(StringUtils.isNotBlank(bizProjectMemberAlteration.getProjectAlterationId()),"PROJECT_ALTERATION_ID",bizProjectMemberAlteration.getProjectAlterationId());
            memberMapper.delete(queryWrapper);
        }catch (Exception exception){
            res = "操作失败！" + exception.getMessage();
        }
        return res;
    }
    //endregion

    //region 变更预算从表

    /**
     * 查询变更预算从表
     * @param bizProjectBudgetAlteration
     * @param proId
     * @return
     */
    public List<DmBudgetSubject> getBudgetList(BizProjectBudgetAlteration bizProjectBudgetAlteration,String proId){
        List<DmBudgetSubject> subjectList = new ArrayList<>();
        try{
            //先获取预算科目
            VProject base = projectInitService.baseDetail(proId);
            DmBudgetStandardVo dmBudgetStandardVo = budgetStandardService.selectDmBudgetStandardByID(base.getBudgetStandardId());
            subjectList = dmBudgetStandardVo.getSubjectList();

            //预算变更信息
            QueryWrapper<BizProjectBudgetAlteration> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("PROJECT_ALTERATION_ID",bizProjectBudgetAlteration.getProjectAlterationId());
            List<BizProjectBudgetAlteration> budgetAlterInfo = budgetMapper.selectList(queryWrapper);

            Map<String,BizProjectBudgetAlteration> budgetFeeMap = budgetAlterInfo.stream().collect(Collectors.toMap(BizProjectBudgetAlteration::getSubjectCode, item->item));
            subjectList.forEach(node -> assignValueToNode(node,budgetFeeMap));
        }catch (Exception exception){
            String str = exception.getMessage();
        }
        return subjectList;
    }

    /**
     * 根据subject的id从映射中检索对应的Fee对象
     * @param subjects 预算科目
     * @param budgetFeeMap 预算费用
     */
    public static void assignValueToNode(DmBudgetSubject subjects,Map<String,BizProjectBudgetAlteration> budgetFeeMap){
        BizProjectBudgetAlteration budgetAlteration = budgetFeeMap.get(subjects.getCode());
        if(budgetAlteration != null){
            if(StringUtils.isNotBlank(budgetAlteration.getBudgetFeeChange())){
                subjects.setBudgetFeeChange(BigDecimal.valueOf(Double.parseDouble(budgetAlteration.getBudgetFeeChange())/10000));
            }

            if(StringUtils.isNotBlank(budgetAlteration.getBeforeAlterBudgetFee())){
                subjects.setBeforeAlterBudgetFee(BigDecimal.valueOf(Double.parseDouble(budgetAlteration.getBeforeAlterBudgetFee())/10000));
            }

            if(StringUtils.isNotBlank(budgetAlteration.getAfterAlterBudgetFee())){
                subjects.setAfterAlterBudgetFee(BigDecimal.valueOf(Double.parseDouble(budgetAlteration.getAfterAlterBudgetFee())/10000));
            }
            subjects.setAlterId(budgetAlteration.getProjectAlterationId());
            subjects.setBudgetType(budgetAlteration.getBudgetType());
        }
        subjects.getChildren().forEach(child->assignValueToNode(child,budgetFeeMap));
    }

    /**
     * 保存预算变更从表信息
     * @param budgetAlterationList
     * @param alterId
     * @return
     */
    public String saveBudgetInfos(List<BizProjectBudgetAlteration> budgetAlterationList,String alterId){
        String res = "操作成功！";
        try{
            //先全部删除
            BizProjectBudgetAlteration bizProjectBudgetAlteration = new BizProjectBudgetAlteration();
            bizProjectBudgetAlteration.setProjectAlterationId(alterId);
            deleteBudgetInfos(bizProjectBudgetAlteration);
            //再全部插入
            budgetAlterationList.forEach(budgetAlteration->{
                //处理金额为元，保留两位小数
                if(StringUtils.isNotBlank(budgetAlteration.getBudgetFeeChange())){
                    budgetAlteration.setBudgetFeeChange(Double.toString(Double.parseDouble(budgetAlteration.getBudgetFeeChange())*10000));
                }
                if(StringUtils.isNotBlank(budgetAlteration.getBeforeAlterBudgetFee())){
                    budgetAlteration.setBeforeAlterBudgetFee(Double.toString(Double.parseDouble(budgetAlteration.getBeforeAlterBudgetFee())*10000));
                }
                if(StringUtils.isNotBlank(budgetAlteration.getAfterAlterBudgetFee())){
                    budgetAlteration.setAfterAlterBudgetFee(Double.toString(Double.parseDouble(budgetAlteration.getAfterAlterBudgetFee())*10000));
                }
                budgetAlteration.setProjectAlterationId(alterId);
                budgetMapper.insert(budgetAlteration);
            });
        }catch (Exception exception){
            res = "操作失败！" + exception.getMessage();
        }
        return res;
    }

    /**
     * 删除变更预算信息
     * @param bizProjectBudgetAlteration
     * @return
     */
    public String deleteBudgetInfos(BizProjectBudgetAlteration bizProjectBudgetAlteration){
        String res = "操作成功！";
        try {
            QueryWrapper<BizProjectBudgetAlteration> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(StringUtils.isNotBlank(bizProjectBudgetAlteration.getProjectAlterationId()),"PROJECT_ALTERATION_ID",bizProjectBudgetAlteration.getProjectAlterationId());
            budgetMapper.delete(queryWrapper);
        }catch (Exception exception){
            res = "操作失败！" + exception.getMessage();
        }
        return res;
    }

    /**
     * 根据项目号获取预算变更记录
     * @param proId
     * @return
     */
    public List<BudgetAlterationHistoryVo> getBudgetChangeListByProId(String proId){
        try{
             return budgetMapper.getBudgetChangeListByProId(proId);
        } catch (Exception exception){
            return null;
        }
    }
    //endregion

    //region 变更通过审核后业务处理

    /**
     * 变更申请审核通过后根据对应的变更类型进行对应业务
     * @param tableName
     * @param businessId
     * @param checkStatus
     * @param sysUserId
     */
    @Override
    public void updateBusinessStatus(String tableName, String businessId, String checkStatus, String sysUserId) {
        try{
            if ("2".equals(checkStatus)){
                BizProjectAlteration proAlteration = alterationMapper.selectById(businessId);//当前的变更信息
                String alterType = proAlteration.getAlterType();
                String proClass = proAlteration.getClassId();
                String proId = proAlteration.getProjectId();

                BizXjProject xjProject = new BizXjProject();
                BizZxProject zxProject = new BizZxProject();
                BizYfContract yfContract = new BizYfContract();

                if(alterType.contains("middleStop")){
                    //中止变更(校、纵、横)：项目状态置为 中止
                    xjProject.setProjectStatusId("2");
                    zxProject.setProjectStatusId("2");
                    yfContract.setProjectStatusId("2");
                }

                if(alterType.contains("delayFinish")){
                    //延期变更(校、纵、横)：项目计划结项时间置为 延期时间
                    xjProject.setPlanEndDate(proAlteration.getChangePlanEndDate());
                    zxProject.setPlanEndDate(proAlteration.getChangePlanEndDate());
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                    yfContract.setPlanEndDate(dateFormat.parse(proAlteration.getChangePlanEndDate())); //String转date
                }

                if(alterType.contains("chargerName")){
                    //负责人变更（横）：姓名、code，原负责人的参与类型变为参与，新增一条负责人信息
                    yfContract.setChargerName(proAlteration.getChangeChargerName()); //取变更后的信息
                    yfContract.setChargerCode(proAlteration.getChangeChargerCode());

                    //根据更改后的负责人code获取其所在的单位和单位名称，作为主表的单位id和单位名称
                    if(StringUtils.isNotBlank(proAlteration.getChangeChargerCode())){
                        SciencePersonVo sciencePersonVo = new SciencePersonVo();
                        sciencePersonVo.setId(proAlteration.getChangeChargerCode());
                        List<SciencePersonBo> sciencePersonBos = sciencePersonMapper.selectPersonDetails(sciencePersonVo);
                        if (!sciencePersonBos.isEmpty()){
                            SciencePersonBo sciencePersonBo = sciencePersonBos.get(0);
                            yfContract.setUnitName(sciencePersonBo.getUnitName());
                            yfContract.setUnitId(sciencePersonBo.getUnitId());
                            yfContract.setChargerEmail(StringUtils.isNotBlank(sciencePersonBo.getEmail())?sciencePersonBo.getEmail():"");
                            yfContract.setChargerPhone(StringUtils.isNotBlank(sciencePersonBo.getMobile())?sciencePersonBo.getMobile():"");

                            //当前变更信息里的部分字段也要处理（单位、负责人）
                            proAlteration.setUnitId(sciencePersonBo.getUnitId());
                            proAlteration.setUnitName(sciencePersonBo.getUnitName());
//                            proAlteration.setChargerCode(proAlteration.getChangeChargerCode());
                        }
                    }

                    if(StringUtils.isNotBlank(yfContract.getChargerType())&&yfContract.getChargerType().equals("3") || !StringUtils.isNotBlank(yfContract.getChargerType())){
                        yfContract.setChargerType("1"); //如果原来的负责人类型是校外，改为教师
                    }

                    //处理成员从表
                    BizProjectMemberAlteration memberAlteration = new BizProjectMemberAlteration();
                    memberAlteration.setPersonId(proAlteration.getChangeChargerCode());
                    //获取原项目信息中的负责人类型
                    memberAlteration.setMemberType(yfContractService.getYfBase(proAlteration.getProjectId()).getChargerType());
                    List<BizProjectMemberAlteration> list = new ArrayList<>();
                    list.add(memberAlteration);
                    projectMemberService.changeMemberInfo(proId,proClass,"chargerName",list);
                }

                if(alterType.contains("mandatary")){
                    //项目委托(校、纵)
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

                    xjProject.setMandatarycode(proAlteration.getMandatarycode());
                    xjProject.setMandataryname(proAlteration.getMandataryname());
                    xjProject.setMandatarybegindate(dateFormat.parse(proAlteration.getMandatarybegindate()));
                    xjProject.setMandataryenddate(dateFormat.parse(proAlteration.getMandataryenddate()));

                    zxProject.setMandatarycode(proAlteration.getMandatarycode());
                    zxProject.setMandataryname(proAlteration.getMandataryname());
                    zxProject.setMandatarybegindate(proAlteration.getMandatarybegindate());
                    zxProject.setMandataryenddate(proAlteration.getMandataryenddate());
                }

                if(alterType.contains("feeAuthorize")){
                    //合同经费变更(横)
                    yfContract.setFeeAuthorize(new BigDecimal(proAlteration.getChangeFeeAuthorize())); //String转BigDecimal
                }

                if(alterType.contains("member")){
                    //成员变更（校级、纵向）
                    BizProjectMemberAlteration bizProjectMemberAlteration = new BizProjectMemberAlteration();
                    bizProjectMemberAlteration.setProjectAlterationId(businessId);
                    List<BizProjectMemberAlteration> list = this.getMemberList(bizProjectMemberAlteration);
                    projectMemberService.changeMemberInfo(proId,proClass,"member",list);
                }

                if(alterType.contains("liuxiaoBudget")){
                    //留校预算变更（校级、纵向）
                    QueryWrapper<BizProjectBudgetAlteration> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("PROJECT_ALTERATION_ID",businessId);
                    List<BizProjectBudgetAlteration> list = budgetMapper.selectList(queryWrapper);
                    projectBudgetService.changeBudgetInfo(proId,list,proClass);
                }

                //更新主表字段
                if(proClass.equals("xJProject")){
                    xjProject.setId(proId);
                    checkCommon.updatZB(xjProject);
                }else if(proClass.equals("zXProject")){
                    zxProject.setId(proId);
                    checkCommon.updatZB(zxProject);
                }else{
                    yfContract.setId(proId);
//                    yfContract.setProjectStatusId("2"); //不记得为什么会写这行代码了，暂时注释掉
                    checkCommon.updatZB(yfContract);
                }
            }
        }catch (Exception exception){
            String ex = exception.getMessage();
        }
    }
    //endregion
}
